Week 21 Ask a Manager Salary Survey, data from Ask a Manager
library(tidyverse)
library(scales)
library(ggtext)
library(gghalves)
library(ggbeeswarm)
library(colorspace)
library(ggsci)
theme_set(theme_minimal(base_size=10))
survey <- readr::read_csv('https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2021/2021-05-18/survey.csv')
── Column specification ──────────────────────────────────────────────────────────────────────────────
cols(
timestamp = col_character(),
how_old_are_you = col_character(),
industry = col_character(),
job_title = col_character(),
additional_context_on_job_title = col_character(),
annual_salary = col_double(),
other_monetary_comp = col_character(),
currency = col_character(),
currency_other = col_character(),
additional_context_on_income = col_character(),
country = col_character(),
state = col_character(),
city = col_character(),
overall_years_of_professional_experience = col_character(),
years_of_experience_in_field = col_character(),
highest_level_of_education_completed = col_character(),
gender = col_character(),
race = col_character()
)
survey %>% summarise(across(everything(), ~mean(!is.na(.)))) %>%
gather() %>%
mutate(key= fct_reorder(key, value)) %>%
mutate(col=ifelse(value==1, "1","0")) %>%
ggplot(aes(key, value)) +
geom_segment( aes(x=key, xend=key, y=0, yend=value), color="slategrey", linetype="dotted") +
geom_point(aes(color=col),size=3) +
geom_text(aes(label= scales::percent(value, accuracy=0.1)),
nudge_y=0.07, size=3) +
theme(
panel.grid.major.x = element_blank(),
panel.grid.minor.x = element_blank(),
panel.grid.major.y = element_blank(),
plot.title.position = "plot",
legend.position="none",
axis.text.x=element_blank()) +
labs(x="Feature", y="% of data present") +
coord_flip() +
scale_color_npg() +
labs(title ="Missing data")

survey %>%
filter(currency=="USD") %>%
filter(!is.na(gender)) %>%
filter(gender!="Prefer not to answer") %>%
mutate(gender=recode_factor(gender,`Other or prefer not to answer`="Other")) %>%
ggplot(aes(x=gender,
y=annual_salary, fill=gender, color=gender)) +
geom_point(position=position_jitter(0.15),size=1, alpha=0.3,shape=as.numeric(16)) +
geom_flat_violin(position= position_nudge(x=0.25, y=0),adjust=2,alpha=0.9, trim='TRUE',scale='width') +
geom_boxplot(aes(x=gender,y=annual_salary,fill=gender), position=position_nudge(x=0.25, y=0),
width=0.1, outlier.shape = NA, varwidth=FALSE, color="black", alpha=0.3) +
scale_fill_manual(values=c("#364958","#3b6064","#55828b","#87bba2"))+
scale_color_manual(values=c("#364958","#3b6064","#55828b","#87bba2")) +
scale_y_continuous(limits=c(0,500000),labels=unit_format(unit = "K", scale = 1e-3, sep = ""),
expand=c(0,0)) +
coord_flip() +
theme(legend.position="none",
plot.title.position = "plot",
plot.title=element_text(face="bold", size=18),
axis.title.y=ggtext::element_markdown(size=9),
axis.title.x=ggtext::element_markdown(size=9),
plot.margin=ggplot2::margin(1,1.5,0.5,1,"cm"),
plot.caption=element_text(size=8, color="#4a4e69")) +
expand_limits(x = 4.25) +
labs(x="**Gender**",y='<br>**Annual Salary** (in USD)',
title="Gender and Annual Salary",
subtitle="Differences in gender groups' annual salary that is below USD 500,000\n",
caption="\nTidy Tuesday Week 21 | Data from Ask a Manager Survey")

# US subset
survey_us = survey %>%
mutate(country=tolower(country)) %>%
mutate(country=str_remove_all(country,"[.]")) %>%
filter(country %in% c("united states","usa","us","united states of america"))
survey %>%
mutate(country=tolower(country)) %>%
mutate(country=str_remove_all(country,"[.]")) %>%
filter(country %in% c("united states","usa","us","united states of america")) %>% count()
# usd subset
survey_usd = survey %>% filter(currency=="USD")
# Field exp and annual salary(below 500k USD)
survey_usd %>%
mutate(exp_field = ifelse(years_of_experience_in_field %in% c("21 - 30 years","31 - 40 years","41 years or more"),">20",years_of_experience_in_field)) %>%
mutate(exp_field = ifelse(exp_field=="1 year or less","<1",exp_field)) %>%
mutate(exp_field=str_remove(exp_field,"years")) %>%
mutate(exp_field=str_replace_all(exp_field, fixed(" "), "")) %>%
ggplot(aes(y=annual_salary,x=factor(exp_field,levels=c("<1","2-4","5-7","8-10","11-20",">20")),color=exp_field, fill=exp_field)) +
geom_half_boxplot(outlier.size=-1, alpha=0.2, show.legend = F) +
geom_half_point(alpha=0.5, size=0.6, show.legend = F) +
#geom_beeswarm(beeswarmArgs = list(side = 1)) +
scale_y_continuous(limits=c(0,500000),labels=unit_format(unit = "K", scale = 1e-3, sep = "")) +
scale_color_npg() +
scale_fill_npg() +
theme(plot.title.position = "plot",
axis.title.y=ggtext::element_markdown(size=9),
axis.title.x=ggtext::element_markdown(size=9),) +
labs(x="**Field experience** (in years)", y= "**Annual salary** (in USD)",
title="Field Experience and Annual Income (<US$500,000)",
subtitle="")

# industry
survey_ind = survey %>% filter(currency=="USD") %>% group_by(industry) %>% tally(sort=T) %>% filter(n>1000)
survey_usd %>%
filter(industry %in% survey_ind$industry) %>%
ggplot(aes(x=industry, y=annual_salary, color=industry, fill=industry)) +
geom_half_violin(show.legend=F,position=position_nudge(x=-0.05, y=0), alpha=0.85) +
#geom_half_boxplot(outlier.size=-1, alpha=0.2, show.legend = F) +
geom_half_boxplot(side="r",show.legend = F,fill=NA) +
scale_x_discrete(labels = function(x) stringr::str_wrap(x, width = 15)) +
scale_y_continuous(limits=c(0,500000),labels=unit_format(unit = "K", scale = 1e-3, sep = "")) +
scale_color_npg() +
scale_fill_npg() +
theme(plot.title.position = "plot") +
labs(x="Industry",y="Annual Salary (in USD)",title="Industry and Annual Income (<US$500,000)")

# industry
survey_job = survey %>% filter(currency=="USD") %>% group_by(job_title) %>% tally(sort=T) %>% filter(n>110)
survey_usd %>%
filter(job_title %in% survey_job$job_title) %>%
ggplot(aes(x=fct_rev(reorder(job_title,annual_salary,median)), y=annual_salary)) +
geom_quasirandom(show.legend=F,alpha=0.5,size=1, color="#ee9b00") +
geom_boxplot(outlier.size=-1,fill=NA, show.legend = F) +
#geom_pointrange(stat = "summary",un.ymin = min,fun.ymax = max,fun.y = median, color="#457b9d", show.legend=F) +
scale_x_discrete(labels = function(x) stringr::str_wrap(x, width = 14)) +
scale_y_continuous(limits=c(0,500000),labels=unit_format(unit = "K", scale = 1e-3, sep = "")) +
theme(plot.title.position = "plot") +
labs(x="Job title",y="Annual salary (in USD)",title="Job Title and Annual Income (<US$500,000)")

survey_usd %>% filter(annual_salary<100000000) -> survey_box
fig = plot_ly(y=survey_box$annual_salary, type="box",quartilemethod="exclusive")
fig
NA
survey_usd %>% group_by(highest_level_of_education_completed) %>% tally(sort=T)
survey_usd %>%
rename(edu=highest_level_of_education_completed) %>%
filter(!is.na(edu)) %>%
ggplot(aes(x=reorder(edu, annual_salary, median), y=annual_salary,
fill=fct_rev(reorder(edu, annual_salary, median)),
color=fct_rev(reorder(edu, annual_salary, median)))) +
geom_point(position=position_jitter(0.15),size=1, alpha=0.4,shape=as.numeric(16)) +
geom_flat_violin(position= position_nudge(x=0.25, y=0),adjust=2,alpha=0.85, trim='TRUE',scale='width') +
geom_boxplot(aes(x=edu,y=annual_salary,
fill=edu), position=position_nudge(x=0.25, y=0),
width=0.1, outlier.shape = NA, varwidth=FALSE, color="black", alpha=0.3) +
scale_y_continuous(limits=c(0,200000),labels=unit_format(unit = "K", scale = 1e-3, sep = ""),
expand=c(0,0)) +
theme(legend.position="none",
plot.title.position = "plot",
axis.title.y=ggtext::element_markdown(size=9),
axis.title.x=ggtext::element_markdown(size=9),
plot.margin=ggplot2::margin(1,1.5,0.5,1,"cm"),
plot.caption=element_text(size=8, color="#4a4e69")) +
expand_limits(x = 6.2) +
scale_x_discrete(labels = function(x) stringr::str_wrap(x, width = 14)) +
scale_color_npg() +
scale_fill_npg() +
coord_flip() +
labs(x="**Education**",y='<br>**Annual Salary** (in USD)',
title="Education and Annual Salary",
subtitle="")

LS0tCnRpdGxlOiAiVGlkeVR1ZXNkYXkgV2VlazIxLzIwMjEiCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KCldlZWsgMjEgW0FzayBhIE1hbmFnZXIgU2FsYXJ5IFN1cnZleV0oaHR0cHM6Ly9naXRodWIuY29tL3Jmb3JkYXRhc2NpZW5jZS90aWR5dHVlc2RheS9ibG9iL21hc3Rlci9kYXRhLzIwMjEvMjAyMS0wNS0xOC9yZWFkbWUubWQpLCBkYXRhIGZyb20gW0FzayBhIE1hbmFnZXJdKGh0dHBzOi8vZG9jcy5nb29nbGUuY29tL3NwcmVhZHNoZWV0cy9kLzFJUFM1ZEJTR3R3WVZianNmYmFNQ1lJV25PdVJtSmNiZXF1b2hOeEN5R1Z3L2VkaXQ/cmVzb3VyY2VrZXkjZ2lkPTE2MjU0MDg3OTIpCgpgYGB7cn0KbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoc2NhbGVzKQpsaWJyYXJ5KGdndGV4dCkKbGlicmFyeShnZ2hhbHZlcykKbGlicmFyeShnZ2JlZXN3YXJtKQoKbGlicmFyeShjb2xvcnNwYWNlKQpsaWJyYXJ5KGdnc2NpKQoKdGhlbWVfc2V0KHRoZW1lX21pbmltYWwoYmFzZV9zaXplPTEwKSkKYGBgCgpgYGB7cn0Kc3VydmV5IDwtIHJlYWRyOjpyZWFkX2NzdignaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL3Jmb3JkYXRhc2NpZW5jZS90aWR5dHVlc2RheS9tYXN0ZXIvZGF0YS8yMDIxLzIwMjEtMDUtMTgvc3VydmV5LmNzdicpCmBgYAoKCgpgYGB7cn0Kc3VydmV5ICU+JSBzdW1tYXJpc2UoYWNyb3NzKGV2ZXJ5dGhpbmcoKSwgfm1lYW4oIWlzLm5hKC4pKSkpICU+JSAKICBnYXRoZXIoKSAlPiUKICBtdXRhdGUoa2V5PSBmY3RfcmVvcmRlcihrZXksIHZhbHVlKSkgJT4lCiAgbXV0YXRlKGNvbD1pZmVsc2UodmFsdWU9PTEsICIxIiwiMCIpKSAlPiUKICBnZ3Bsb3QoYWVzKGtleSwgdmFsdWUpKSArCiAgZ2VvbV9zZWdtZW50KCBhZXMoeD1rZXksIHhlbmQ9a2V5LCB5PTAsIHllbmQ9dmFsdWUpLCBjb2xvcj0ic2xhdGVncmV5IiwgbGluZXR5cGU9ImRvdHRlZCIpICsgCiAgZ2VvbV9wb2ludChhZXMoY29sb3I9Y29sKSxzaXplPTMpICsKICBnZW9tX3RleHQoYWVzKGxhYmVsPSBzY2FsZXM6OnBlcmNlbnQodmFsdWUsIGFjY3VyYWN5PTAuMSkpLAogICAgICAgICAgICBudWRnZV95PTAuMDcsIHNpemU9MykgKyAKICB0aGVtZSgKICAgIHBhbmVsLmdyaWQubWFqb3IueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIHBhbmVsLmdyaWQubWlub3IueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIHBsb3QudGl0bGUucG9zaXRpb24gPSAicGxvdCIsCiAgICBsZWdlbmQucG9zaXRpb249Im5vbmUiLAogICAgYXhpcy50ZXh0Lng9ZWxlbWVudF9ibGFuaygpKSArIAogIGxhYnMoeD0iRmVhdHVyZSIsIHk9IiUgb2YgZGF0YSBwcmVzZW50IikgKyAKICBjb29yZF9mbGlwKCkgKyAKICBzY2FsZV9jb2xvcl9ucGcoKSArIAogIGxhYnModGl0bGUgPSJNaXNzaW5nIGRhdGEiKQpgYGAKCgoKCmBgYHtyLCB3YXJuaW5nPUYsIGZpZy53aWR0aD0zLjgsIGZpZy5oZWlnaHQ9My4yfQpzdXJ2ZXkgJT4lCiAgZmlsdGVyKGN1cnJlbmN5PT0iVVNEIikgJT4lCiAgZmlsdGVyKCFpcy5uYShnZW5kZXIpKSAlPiUKICBmaWx0ZXIoZ2VuZGVyIT0iUHJlZmVyIG5vdCB0byBhbnN3ZXIiKSAlPiUKICBtdXRhdGUoZ2VuZGVyPXJlY29kZV9mYWN0b3IoZ2VuZGVyLGBPdGhlciBvciBwcmVmZXIgbm90IHRvIGFuc3dlcmA9Ik90aGVyIikpICU+JQogIGdncGxvdChhZXMoeD1nZW5kZXIsIAogICAgICAgICAgICAgeT1hbm51YWxfc2FsYXJ5LCBmaWxsPWdlbmRlciwgY29sb3I9Z2VuZGVyKSkgKyAKICBnZW9tX3BvaW50KHBvc2l0aW9uPXBvc2l0aW9uX2ppdHRlcigwLjE1KSxzaXplPTEsIGFscGhhPTAuMyxzaGFwZT1hcy5udW1lcmljKDE2KSkgKyAKICBnZW9tX2ZsYXRfdmlvbGluKHBvc2l0aW9uPSBwb3NpdGlvbl9udWRnZSh4PTAuMjUsIHk9MCksYWRqdXN0PTIsYWxwaGE9MC45LCB0cmltPSdUUlVFJyxzY2FsZT0nd2lkdGgnKSArCiAgZ2VvbV9ib3hwbG90KGFlcyh4PWdlbmRlcix5PWFubnVhbF9zYWxhcnksZmlsbD1nZW5kZXIpLCBwb3NpdGlvbj1wb3NpdGlvbl9udWRnZSh4PTAuMjUsIHk9MCksCiAgICAgICAgICAgICAgIHdpZHRoPTAuMSwgb3V0bGllci5zaGFwZSA9IE5BLCB2YXJ3aWR0aD1GQUxTRSwgY29sb3I9ImJsYWNrIiwgYWxwaGE9MC4zKSArIAogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz1jKCIjMzY0OTU4IiwiIzNiNjA2NCIsIiM1NTgyOGIiLCIjODdiYmEyIikpKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9YygiIzM2NDk1OCIsIiMzYjYwNjQiLCIjNTU4MjhiIiwiIzg3YmJhMiIpKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cz1jKDAsNTAwMDAwKSxsYWJlbHM9dW5pdF9mb3JtYXQodW5pdCA9ICJLIiwgc2NhbGUgPSAxZS0zLCBzZXAgPSAiIiksCiAgICAgICAgICAgICAgICAgICAgIGV4cGFuZD1jKDAsMCkpICsKICBjb29yZF9mbGlwKCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiLAogICAgICAgIHBsb3QudGl0bGUucG9zaXRpb24gPSAicGxvdCIsCiAgICAgICAgcGxvdC50aXRsZT1lbGVtZW50X3RleHQoZmFjZT0iYm9sZCIsIHNpemU9MTgpLAogICAgICAgIGF4aXMudGl0bGUueT1nZ3RleHQ6OmVsZW1lbnRfbWFya2Rvd24oc2l6ZT05KSwKICAgICAgICBheGlzLnRpdGxlLng9Z2d0ZXh0OjplbGVtZW50X21hcmtkb3duKHNpemU9OSksCiAgICAgICAgcGxvdC5tYXJnaW49Z2dwbG90Mjo6bWFyZ2luKDEsMS41LDAuNSwxLCJjbSIpLAogICAgICAgIHBsb3QuY2FwdGlvbj1lbGVtZW50X3RleHQoc2l6ZT04LCBjb2xvcj0iIzRhNGU2OSIpKSArCiAgZXhwYW5kX2xpbWl0cyh4ID0gNC4yNSkgKwogIGxhYnMoeD0iKipHZW5kZXIqKiIseT0nPGJyPioqQW5udWFsIFNhbGFyeSoqIChpbiBVU0QpJywKICAgICAgIHRpdGxlPSJHZW5kZXIgYW5kIEFubnVhbCBTYWxhcnkiLAogICAgICAgc3VidGl0bGU9IkRpZmZlcmVuY2VzIGluIGdlbmRlciBncm91cHMnIGFubnVhbCBzYWxhcnkgdGhhdCBpcyBiZWxvdyBVU0QgNTAwLDAwMFxuIiwKICAgICAgIGNhcHRpb249IlxuVGlkeSBUdWVzZGF5IFdlZWsgMjEgfCBEYXRhIGZyb20gQXNrIGEgTWFuYWdlciBTdXJ2ZXkiKQpgYGAKCmBgYHtyfQojIFVTIHN1YnNldApzdXJ2ZXlfdXMgPSBzdXJ2ZXkgJT4lIAogIG11dGF0ZShjb3VudHJ5PXRvbG93ZXIoY291bnRyeSkpICU+JQogIG11dGF0ZShjb3VudHJ5PXN0cl9yZW1vdmVfYWxsKGNvdW50cnksIlsuXSIpKSAlPiUKICBmaWx0ZXIoY291bnRyeSAlaW4lIGMoInVuaXRlZCBzdGF0ZXMiLCJ1c2EiLCJ1cyIsInVuaXRlZCBzdGF0ZXMgb2YgYW1lcmljYSIpKSAKCnN1cnZleSAlPiUgCiAgbXV0YXRlKGNvdW50cnk9dG9sb3dlcihjb3VudHJ5KSkgJT4lCiAgbXV0YXRlKGNvdW50cnk9c3RyX3JlbW92ZV9hbGwoY291bnRyeSwiWy5dIikpICU+JQogIGZpbHRlcihjb3VudHJ5ICVpbiUgYygidW5pdGVkIHN0YXRlcyIsInVzYSIsInVzIiwidW5pdGVkIHN0YXRlcyBvZiBhbWVyaWNhIikpICU+JSBjb3VudCgpCmBgYAoKYGBge3IsIHdhcm5pbmc9RiwgbWVzc2FnZT1GfQojIHVzZCBzdWJzZXQKc3VydmV5X3VzZCA9IHN1cnZleSAlPiUgZmlsdGVyKGN1cnJlbmN5PT0iVVNEIikKCiMgRmllbGQgZXhwIGFuZCBhbm51YWwgc2FsYXJ5KGJlbG93IDUwMGsgVVNEKQogc3VydmV5X3VzZCAlPiUKICBtdXRhdGUoZXhwX2ZpZWxkID0gaWZlbHNlKHllYXJzX29mX2V4cGVyaWVuY2VfaW5fZmllbGQgJWluJSBjKCIyMSAtIDMwIHllYXJzIiwiMzEgLSA0MCB5ZWFycyIsIjQxIHllYXJzIG9yIG1vcmUiKSwiPjIwIix5ZWFyc19vZl9leHBlcmllbmNlX2luX2ZpZWxkKSkgJT4lCiAgbXV0YXRlKGV4cF9maWVsZCA9IGlmZWxzZShleHBfZmllbGQ9PSIxIHllYXIgb3IgbGVzcyIsIjwxIixleHBfZmllbGQpKSAlPiUKICBtdXRhdGUoZXhwX2ZpZWxkPXN0cl9yZW1vdmUoZXhwX2ZpZWxkLCJ5ZWFycyIpKSAlPiUKICBtdXRhdGUoZXhwX2ZpZWxkPXN0cl9yZXBsYWNlX2FsbChleHBfZmllbGQsIGZpeGVkKCIgIiksICIiKSkgJT4lCiAgZ2dwbG90KGFlcyh5PWFubnVhbF9zYWxhcnkseD1mYWN0b3IoZXhwX2ZpZWxkLGxldmVscz1jKCI8MSIsIjItNCIsIjUtNyIsIjgtMTAiLCIxMS0yMCIsIj4yMCIpKSxjb2xvcj1leHBfZmllbGQsIGZpbGw9ZXhwX2ZpZWxkKSkgKwogIGdlb21faGFsZl9ib3hwbG90KG91dGxpZXIuc2l6ZT0tMSwgYWxwaGE9MC4yLCBzaG93LmxlZ2VuZCA9IEYpICsKICBnZW9tX2hhbGZfcG9pbnQoYWxwaGE9MC41LCBzaXplPTAuNiwgc2hvdy5sZWdlbmQgPSBGKSArIAogICNnZW9tX2JlZXN3YXJtKGJlZXN3YXJtQXJncyA9IGxpc3Qoc2lkZSA9IDEpKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cz1jKDAsNTAwMDAwKSxsYWJlbHM9dW5pdF9mb3JtYXQodW5pdCA9ICJLIiwgc2NhbGUgPSAxZS0zLCBzZXAgPSAiIikpICsgCiAgc2NhbGVfY29sb3JfbnBnKCkgKyAKICBzY2FsZV9maWxsX25wZygpICsgCiAgdGhlbWUocGxvdC50aXRsZS5wb3NpdGlvbiA9ICJwbG90IiwKICAgICAgICBheGlzLnRpdGxlLnk9Z2d0ZXh0OjplbGVtZW50X21hcmtkb3duKHNpemU9OSksCiAgICAgICAgYXhpcy50aXRsZS54PWdndGV4dDo6ZWxlbWVudF9tYXJrZG93bihzaXplPTkpLCkgKwogIGxhYnMoeD0iKipGaWVsZCBleHBlcmllbmNlKiogKGluIHllYXJzKSIsIHk9ICIqKkFubnVhbCBzYWxhcnkqKiAoaW4gVVNEKSIsCiAgICAgICB0aXRsZT0iRmllbGQgRXhwZXJpZW5jZSBhbmQgQW5udWFsIEluY29tZSAoPFVTJDUwMCwwMDApIiwKICAgICAgIHN1YnRpdGxlPSIiKQpgYGAKCgpgYGB7ciwgd2FybmluZz1GLCBtZXNzYWdlPUZ9CiMgaW5kdXN0cnkKc3VydmV5X2luZCA9IHN1cnZleSAlPiUgZmlsdGVyKGN1cnJlbmN5PT0iVVNEIikgJT4lIGdyb3VwX2J5KGluZHVzdHJ5KSAlPiUgdGFsbHkoc29ydD1UKSAlPiUgZmlsdGVyKG4+MTAwMCkKc3VydmV5X3VzZCAlPiUgCiAgZmlsdGVyKGluZHVzdHJ5ICVpbiUgc3VydmV5X2luZCRpbmR1c3RyeSkgJT4lCiAgZ2dwbG90KGFlcyh4PWluZHVzdHJ5LCB5PWFubnVhbF9zYWxhcnksIGNvbG9yPWluZHVzdHJ5LCBmaWxsPWluZHVzdHJ5KSkgKwogIGdlb21faGFsZl92aW9saW4oc2hvdy5sZWdlbmQ9Rixwb3NpdGlvbj1wb3NpdGlvbl9udWRnZSh4PS0wLjA1LCB5PTApLCBhbHBoYT0wLjg1KSArCiAgI2dlb21faGFsZl9ib3hwbG90KG91dGxpZXIuc2l6ZT0tMSwgYWxwaGE9MC4yLCBzaG93LmxlZ2VuZCA9IEYpICsKICBnZW9tX2hhbGZfYm94cGxvdChzaWRlPSJyIixzaG93LmxlZ2VuZCA9IEYsZmlsbD1OQSkgKwogIHNjYWxlX3hfZGlzY3JldGUobGFiZWxzID0gZnVuY3Rpb24oeCkgc3RyaW5ncjo6c3RyX3dyYXAoeCwgd2lkdGggPSAxNSkpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzPWMoMCw1MDAwMDApLGxhYmVscz11bml0X2Zvcm1hdCh1bml0ID0gIksiLCBzY2FsZSA9IDFlLTMsIHNlcCA9ICIiKSkgKwogIHNjYWxlX2NvbG9yX25wZygpICsgCiAgc2NhbGVfZmlsbF9ucGcoKSArCiAgdGhlbWUocGxvdC50aXRsZS5wb3NpdGlvbiA9ICJwbG90IikgKyAKICBsYWJzKHg9IkluZHVzdHJ5Iix5PSJBbm51YWwgU2FsYXJ5IChpbiBVU0QpIix0aXRsZT0iSW5kdXN0cnkgYW5kIEFubnVhbCBJbmNvbWUgKDxVUyQ1MDAsMDAwKSIpCmBgYAoKCmBgYHtyLHdhcm5pbmc9RiwgbWVzc2FnZT1GfQojIGluZHVzdHJ5CnN1cnZleV9qb2IgPSBzdXJ2ZXkgJT4lIGZpbHRlcihjdXJyZW5jeT09IlVTRCIpICU+JSBncm91cF9ieShqb2JfdGl0bGUpICU+JSB0YWxseShzb3J0PVQpICU+JSBmaWx0ZXIobj4xMTApCnN1cnZleV91c2QgJT4lIAogIGZpbHRlcihqb2JfdGl0bGUgJWluJSBzdXJ2ZXlfam9iJGpvYl90aXRsZSkgJT4lCiAgZ2dwbG90KGFlcyh4PWZjdF9yZXYocmVvcmRlcihqb2JfdGl0bGUsYW5udWFsX3NhbGFyeSxtZWRpYW4pKSwgeT1hbm51YWxfc2FsYXJ5KSkgKwogIGdlb21fcXVhc2lyYW5kb20oc2hvdy5sZWdlbmQ9RixhbHBoYT0wLjUsc2l6ZT0xLCBjb2xvcj0iI2VlOWIwMCIpICsKICBnZW9tX2JveHBsb3Qob3V0bGllci5zaXplPS0xLGZpbGw9TkEsIHNob3cubGVnZW5kID0gRikgKwogICNnZW9tX3BvaW50cmFuZ2Uoc3RhdCA9ICJzdW1tYXJ5Iix1bi55bWluID0gbWluLGZ1bi55bWF4ID0gbWF4LGZ1bi55ID0gbWVkaWFuLCBjb2xvcj0iIzQ1N2I5ZCIsIHNob3cubGVnZW5kPUYpICsKICBzY2FsZV94X2Rpc2NyZXRlKGxhYmVscyA9IGZ1bmN0aW9uKHgpIHN0cmluZ3I6OnN0cl93cmFwKHgsIHdpZHRoID0gMTQpKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cz1jKDAsNTAwMDAwKSxsYWJlbHM9dW5pdF9mb3JtYXQodW5pdCA9ICJLIiwgc2NhbGUgPSAxZS0zLCBzZXAgPSAiIikpICsKICB0aGVtZShwbG90LnRpdGxlLnBvc2l0aW9uID0gInBsb3QiKSArCiAgbGFicyh4PSJKb2IgdGl0bGUiLHk9IkFubnVhbCBzYWxhcnkgKGluIFVTRCkiLHRpdGxlPSJKb2IgVGl0bGUgYW5kIEFubnVhbCBJbmNvbWUgKDxVUyQ1MDAsMDAwKSIpCgpgYGAKCgpgYGB7cn0Kc3VydmV5X3VzZCAlPiUgZmlsdGVyKGFubnVhbF9zYWxhcnk8MTAwMDAwMDAwKSAtPiBzdXJ2ZXlfYm94CmZpZyA9IHBsb3RfbHkoeT1zdXJ2ZXlfYm94JGFubnVhbF9zYWxhcnksIHR5cGU9ImJveCIscXVhcnRpbGVtZXRob2Q9ImV4Y2x1c2l2ZSIpIApmaWcKICAKYGBgCgpgYGB7cn0Kc3VydmV5X3VzZCAlPiUgZ3JvdXBfYnkoaGlnaGVzdF9sZXZlbF9vZl9lZHVjYXRpb25fY29tcGxldGVkKSAlPiUgdGFsbHkoc29ydD1UKQpgYGAKCgpgYGB7ciwgd2FybmluZz1GLCBtZXNzYWdlPUYsIGZpZy53aWR0aD00LCBmaWcuaGVpZ2h0PTMuNX0Kc3VydmV5X3VzZCAlPiUKICByZW5hbWUoZWR1PWhpZ2hlc3RfbGV2ZWxfb2ZfZWR1Y2F0aW9uX2NvbXBsZXRlZCkgJT4lCiAgZmlsdGVyKCFpcy5uYShlZHUpKSAlPiUKICBnZ3Bsb3QoYWVzKHg9cmVvcmRlcihlZHUsIGFubnVhbF9zYWxhcnksIG1lZGlhbiksIHk9YW5udWFsX3NhbGFyeSwKICAgICAgICAgICAgIGZpbGw9ZmN0X3JldihyZW9yZGVyKGVkdSwgYW5udWFsX3NhbGFyeSwgbWVkaWFuKSksIAogICAgICAgICAgICAgY29sb3I9ZmN0X3JldihyZW9yZGVyKGVkdSwgYW5udWFsX3NhbGFyeSwgbWVkaWFuKSkpKSArIAogIGdlb21fcG9pbnQocG9zaXRpb249cG9zaXRpb25faml0dGVyKDAuMTUpLHNpemU9MSwgYWxwaGE9MC40LHNoYXBlPWFzLm51bWVyaWMoMTYpKSArIAogIGdlb21fZmxhdF92aW9saW4ocG9zaXRpb249IHBvc2l0aW9uX251ZGdlKHg9MC4yNSwgeT0wKSxhZGp1c3Q9MixhbHBoYT0wLjg1LCB0cmltPSdUUlVFJyxzY2FsZT0nd2lkdGgnKSArCiAgZ2VvbV9ib3hwbG90KGFlcyh4PWVkdSx5PWFubnVhbF9zYWxhcnksCiAgICAgICAgICAgICAgICAgICBmaWxsPWVkdSksIHBvc2l0aW9uPXBvc2l0aW9uX251ZGdlKHg9MC4yNSwgeT0wKSwKICAgICAgICAgICAgICAgd2lkdGg9MC4xLCBvdXRsaWVyLnNoYXBlID0gTkEsIHZhcndpZHRoPUZBTFNFLCBjb2xvcj0iYmxhY2siLCBhbHBoYT0wLjMpICsgCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cz1jKDAsMjAwMDAwKSxsYWJlbHM9dW5pdF9mb3JtYXQodW5pdCA9ICJLIiwgc2NhbGUgPSAxZS0zLCBzZXAgPSAiIiksCiAgICAgICAgICAgICAgICAgICAgIGV4cGFuZD1jKDAsMCkpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiLAogICAgICAgIHBsb3QudGl0bGUucG9zaXRpb24gPSAicGxvdCIsCiAgICAgICAgYXhpcy50aXRsZS55PWdndGV4dDo6ZWxlbWVudF9tYXJrZG93bihzaXplPTkpLAogICAgICAgIGF4aXMudGl0bGUueD1nZ3RleHQ6OmVsZW1lbnRfbWFya2Rvd24oc2l6ZT05KSwKICAgICAgICBwbG90Lm1hcmdpbj1nZ3Bsb3QyOjptYXJnaW4oMSwxLjUsMC41LDEsImNtIiksCiAgICAgICAgcGxvdC5jYXB0aW9uPWVsZW1lbnRfdGV4dChzaXplPTgsIGNvbG9yPSIjNGE0ZTY5IikpICsKICBleHBhbmRfbGltaXRzKHggPSA2LjIpICsKICBzY2FsZV94X2Rpc2NyZXRlKGxhYmVscyA9IGZ1bmN0aW9uKHgpIHN0cmluZ3I6OnN0cl93cmFwKHgsIHdpZHRoID0gMTQpKSArCiAgc2NhbGVfY29sb3JfbnBnKCkgKyAKICBzY2FsZV9maWxsX25wZygpICsgCiAgY29vcmRfZmxpcCgpICsgCiAgbGFicyh4PSIqKkVkdWNhdGlvbioqIix5PSc8YnI+KipBbm51YWwgU2FsYXJ5KiogKGluIFVTRCknLAogICAgICAgdGl0bGU9IkVkdWNhdGlvbiBhbmQgQW5udWFsIFNhbGFyeSIsCiAgICAgICBzdWJ0aXRsZT0iIikKYGBgCgoKCgoKCiAg